使用 Spring Cloud Gateway + Ribbon 负载均衡实战 您所在的位置:网站首页 ribbon 负载策略 使用 Spring Cloud Gateway + Ribbon 负载均衡实战

使用 Spring Cloud Gateway + Ribbon 负载均衡实战

2024-07-15 02:43| 来源: 网络整理| 查看: 265

前言

通常我们如果有一个服务,会部署到多台服务器上,这些微服务如果都暴露给客户,是非常难以管理的,我们系统需要有一个唯一的出口,Spring Cloud Gateway 网关是一个服务,是系统的唯一出口。Spring Cloud Gateway 网关封装了系统内部的微服务,为客户端提供一个定制的API。客户端只需要调用网关接口,就可以调用到实际的微服务,实际的服务对客户不可见,并且容易扩展服务。

Spring Cloud Gateway 网关可以结合Ribbon完成负载均衡的功能,可以自动检查微服务的状况,及时剔除或者加入某个微服务到可用服务列表。此外Spring Cloud Gateway 网关可以完成权限检查、限流、统计等功能。下面我们将一一完成上面的功能。注意微服务只是提供rest的接口,不会有额外的组件依赖,不需要eureka等。只需要两个工程,一个是微服务,我们可以部署到多台服务器,那么只是访问的ip不同,在演示的时候,我们在本机演示,修改端口,达到启动多个微服务的目的,另一个就是网关,主要是 Spring Cloud Gateway 和 Ribbon两大组件来实现网关和负载均衡等功能。

1、构建两个工程

这里不再介绍如何构建两个微服务步骤,请自行构建,我建立微服务于情况如下:

1.1、搭建两个微服务,端口为8072、8073

1.2、在controller控制层编写测试接口

1.2、访问地址

http://localhost:8072

http://localhost:8073

2、构建网关微服务

请自行构建网关微服务,我构建的网关微服务名字:esb-gateway,可以使用:https://start.spring.io/

2.1、修改pom.xml文件

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384     4.0.0             org.springframework.boot         spring-boot-starter-parent         2.3.1.RELEASE                 com.modules.scistor     esb-gateway     0.0.1-SNAPSHOT     esb-gateway     Demo project for Spring Boot             1.8         Hoxton.SR3                             org.springframework.boot             spring-boot-starter                             org.springframework.boot             spring-boot-starter-test             test                                                 org.junit.vintage                     junit-vintage-engine                                                                 org.springframework.cloud             spring-cloud-starter-gateway                                     org.springframework.cloud             spring-cloud-starter-netflix-ribbon                                                         org.springframework.cloud                 spring-cloud-dependencies                 ${spring-cloud.version}                 pom                 import                                                                 org.springframework.boot                 spring-boot-maven-plugin                                                     org.apache.maven.plugins                 maven-surefire-plugin                 2.22.2                                     true                                        

2.2、修改application.yml文件

123456789101112131415161718192021222324252627282930313233server:   port: 8070 spring:   cloud:     gateway:       # 跨域配置       globalcors:         cors-configurations:           '[/**]':             allowedOrigins: "*"             allowedMethods:               - GET               - POST               - PUT               - DELETE               - OPTIONS       # 路由负载配置       default-filters:       routes:         - id: my_route           uri: lb://load-balanced-service           predicates:             - Path=/crs/**           filters:             - StripPrefix=1 load-balanced-service:   ribbon:     # 负载地址     listOfServers: http://localhost:8072, http://localhost:8073     # 负载轮询策略     NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule     # 健康检查     NFLoadBalancerPingClassName: com.modules.scistor.config.HealthExamination

注意:

listOfServers:配置的微服务的服务器ip端口,多个用,隔开配置。

NFLoadBalancerRuleClassName:使用的负载均衡策略。

负载均衡策略介绍

RoundRobinRule:简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。

AvailabilityFilteringRule:对以下两种服务器进行忽略:

(1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。

注意:可以通过修改配置loadbalancer..connectionFailureCountThreshold来修改连接失败多少次之后被设置为短路状态。默认是3次。

(2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上线,可以由客户端的..ActiveConnectionsLimit属性进行配置

WeightedResponseTimeRule:为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。

ZoneAvoidanceRule:以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。

BestAvailableRule:忽略哪些短路的服务器,并选择并发数较低的服务器。

RandomRule:随机选择一个可用的服务器。

Retry:重试机制的选择逻辑

自定义负载均衡策略

可以自定义负载均衡算法。需求是:每个服务器访问三次再跳转到下一个服务器。

(1)负载均衡算法(参考RandomRule)

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100package com.modules.scistor.config; import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.AbstractLoadBalancerRule; import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.Server; import java.util.ArrayList; import java.util.List; public class MyRule extends AbstractLoadBalancerRule {     private volatile int total;     private volatile int index;     List upList = new ArrayList();     public MyRule()     {     }     public Server choose(ILoadBalancer lb, Object key)     {         if (lb == null)         {             return null;         }         else         {             Server server = null;             while (server == null)             {                 if (Thread.interrupted())                 {                     return null;                 }                 List allList = lb.getAllServers();                 int serverCount = allList.size();                 if (serverCount == 0)                 {                     return null;                 }                 if (total == 0)                 {                     upList = lb.getReachableServers();                 }                 if (total < 3)                 {                     if (upList.size() != lb.getReachableServers().size())                     {                         index = 0;                     }                     server = lb.getReachableServers().get(index);                     total++;                 }                 else                 {                     total = 0;                     index++;                     if (index >= lb.getReachableServers().size())                     {                         index = 0;                     }                 }                 if (server == null)                 {                     Thread.yield();                 }                 else                 {                     if (server.isAlive())                     {                         return server;                     }                     server = null;                     Thread.yield();                 }             }             return server;         }     }     public Server choose(Object key)     {         return this.choose(this.getLoadBalancer(), key);     }     public void initWithNiwsConfig(IClientConfig clientConfig)     {     } }

(2)修改配置文件

2.3、测试

访问 http://localhost:8070/crs/health

3、健康监测

3.1、新建一个Config类

12345678910111213141516171819package com.modules.scistor.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; /**  * @Auther: lc  * @Date: 2020/7/1 11:37  * @Description: 健康检查配置类  */ @Configuration public class HealthConfig {     @Bean     public RestTemplate restTemplate()     {         return new RestTemplate();     } }

3.2、新建一个健康检查的类,调用heath接口

12345678910111213141516171819202122232425262728293031323334353637383940package com.modules.scistor.config; import com.netflix.loadbalancer.IPing; import com.netflix.loadbalancer.Server; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; /**  * @Auther: lc  * @Date: 2020/7/1 11:39  * @Description: 健康检查实现  */ public class HealthExamination implements IPing {     @Autowired     private RestTemplate restTemplate;     @Override     public boolean isAlive(Server server) {         String url = "http://" + server.getId() + "/health";         try         {             ResponseEntity heath = restTemplate.getForEntity(url, String.class);             if (heath.getStatusCode() == HttpStatus.OK)             {                 System.out.println("ping " + url + " success and response is " + heath.getBody());                 return true;             }             System.out.println("ping " + url + " error and response is " + heath.getBody());             return false;         }         catch (Exception e)         {             System.out.println("ping " + url + " failed");             return false;         }     } }

上面代码继承IPing接口,判断服务是否可用。我们在微服务中增加heath接口,在gateway中调用该接口,如果返回正常则认为微服务可用。

3.3、配置文件修改

3.4、项目结构

至此使用 Spring Cloud Gateway + Ribbon 负载均衡项目实战结束,全文完。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有